import os
from datetime import datetime

from alipay import AliPay
from django.db import transaction
from django.http import JsonResponse
from django.shortcuts import render, redirect

# Create your views here.
from django.urls import reverse

from django.views import View
from django_redis import get_redis_connection

from goods.models import GoodsSKU
from user.models import Address

from order.models import OrderInfo

from order.models import OrderGoods

from dailyfresh import settings
from utils.mixin import LoginRequiredMixin


# /order/place
class OrderPlaceView(LoginRequiredMixin, View):
    """提交订单页面"""

    def post(self, request):
        # 获取到登录的用户信息 组建redis的key、
        user = request.user

        # 获取到提交的数据
        sku_ids = request.POST.getlist('sku_ids')

        print("commit order ids:", sku_ids)

        # 校验参数
        if not sku_ids:
            return redirect(reverse('cart:show'))

        # redis 连接
        conn = get_redis_connection('default')
        cart_key = 'cart_%d' % user.id

        skus = []
        total_count = 0
        total_price = 0

        # 通过商品的id获取到商品的信息
        for sku_id in sku_ids:
            sku = GoodsSKU.objects.get(id=sku_id)
            print(sku)
            # 获取到用户所购买的数量
            count = conn.hget(cart_key, sku_id)
            amount = sku.price * int(count)

            # 动态增加属性
            sku.count = int(count)
            sku.amount = amount

            skus.append(sku)

            total_count += int(count)
            total_price += amount

        # 运费：实际开发的时候，属于一个子系统
        transit_price = 10

        # 实付款
        total_pay = total_price + transit_price

        # 获取到用户所有收件地址 供用户手选
        addrs = Address.objects.filter(user=user)

        sku_ids = ",".join(sku_ids)
        # 组织上下文
        context = {'skus': skus,
                   'total_count': total_count,
                   'total_price': total_price,
                   'transit_price': transit_price,
                   'total_pay': total_pay,
                   'addrs': addrs,
                   'sku_ids': sku_ids}
        print("context:", context)

        return render(request, 'place_order.html', context)


# /order/commit
class OrderCommitView(View):
    """
     用户提交订单生成订单
    """

    @transaction.atomic
    def post(self, request):
        """订单创建"""
        user = request.user
        if not user.is_authenticated:
            # 用户未登录
            return JsonResponse({'res': 0, 'errmsg': '用户未登录'})
        # 接收参数
        addr_id = request.POST.get("addr_id")
        pay_method = request.POST.get("pay_method")
        sku_ids = request.POST.get("sku_ids")

        # 校验参数
        if not all([addr_id, pay_method, sku_ids]):
            return JsonResponse({'res': 1, 'errmsg': '参数不完整'})

        # 校验支付方式
        if pay_method not in OrderInfo.PAY_METHODS:
            return JsonResponse({'res': 2, 'errmsg': '非法的支付方式'})

        # 校验地址
        try:
            addr = Address.objects.get(id=addr_id)
        except Address.DoesNotExist:
            return JsonResponse({'res': 3, 'errmsg': '地址不存在'})

        # TODO: 创建订单核心业务

        # TODO 添加OderInfo信息
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + str(user.id)
        transit_price = 10
        total_count = 0
        total_price = 0

        # TODO 设置一个保存点
        save_id = transaction.savepoint()
        try:

            # 添加记录
            order = OrderInfo.objects.create(order_id=order_id,
                                             user=user,
                                             addr=addr,
                                             pay_method=pay_method,
                                             transit_price=transit_price,
                                             total_count=total_count,
                                             total_price=total_price)

            # TODO 添加OrderGoods信息订单有几个商品添加几条数据

            conn = get_redis_connection('default')
            cart_key = 'cart_%d' % user.id
            sku_ids = sku_ids.split(",")

            for sku_id in sku_ids:
                try:
                    # sku = GoodsSKU.objects.get(id=sku_id)
                    # select * from df_goods_sku where id=17 for update;
                    sku = GoodsSKU.objects.select_for_update().get(id=sku_id)
                except GoodsSKU.DoesNotExist:
                    # 回滚
                    transaction.savepoint_rollback(save_id)
                    return JsonResponse({'res': 4, 'errmsg': '商品不存在'})

                count = conn.hget(cart_key, sku_id)

                # TODO： 判断商品的库存
                if int(count) > sku.stock:
                    transaction.savepoint_rollback(save_id)
                    return JsonResponse({'res': 6, 'errmsg': '商品库存不足'})

                # TODO 更新商品的库存和销量
                sku.stock -= int(count)
                sku.sales += int(count)
                sku.save()

                # 乐观锁 sql
                """
                update df_goods_sku set stock=new_stock,sales=new_sales 
                where id=sku_id and stock=orgin_stock 
                """

                # orgin_stock = sku.stock
                # new_stock = orgin_stock - int(count)
                # new_sales = orgin_stock + int(count)
                # # 返回受影响的行数
                # res = GoodsSKU.objects.filter(id=sku_id, stock=orgin_stock).update(stock=new_stock, sales=new_sales)
                # if res == 0:
                #     transaction.savepoint_rollback(save_id)
                #     return JsonResponse({'res': 7, 'errmsg': '下单失败'})

                OrderGoods.objects.create(order=order,
                                          sku=sku,
                                          count=count,
                                          price=sku.price)

                # TODO 累加计算订单商品的总数量和总价格
                amount = sku.price * int(count)
                total_count += int(count)
                total_price += amount

            # TODO: 更新订单信息表中的商品总数量和总价格
            order.total_count = total_count
            order.total_price = total_price
            order.save()
        except Exception as e:
            transaction.savepoint_rollback(save_id)
            return JsonResponse({'res': 7, 'errmsg': '下单失败'})
        # TODO： 下单成功提交事务
        transaction.savepoint_commit(save_id)
        # TODO: 清除购物车中对应的记录 [1,3] 拆包*
        conn.hdel(cart_key, *sku_ids)

        return JsonResponse({'res': 5, 'errmsg': '订单创建成功'})


# /order/pay
class OrderPayView(View):
    """ 订单支付"""

    def post(self, request):
        # 用户登录
        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': "用户未登录"})
        # 接受参数
        order_id = request.POST.get('order_id')

        # 校验参数
        if not order_id:
            return JsonResponse({'res': 1, 'errmsg': "无效的订单编号"})
        try:
            order = OrderInfo.objects.get(order_id=order_id,
                                          user=user,
                                          pay_method=3,
                                          order_status=1)
        except OrderInfo.DoesNotExist:
            return JsonResponse({'res': 1, 'errmsg': "订单错误"})
        # 业务处理 使用python sdk调用阿里支付接口
        app_private_key_string = open(os.path.join(settings.BASE_DIR, 'apps/order/app_private_key.pem')).read()
        alipay_public_key_string = open(os.path.join(settings.BASE_DIR, 'apps/order/alipay_public_key.pem')).read()
        alipay = AliPay(
            appid="2016102300747753",
            app_notify_url=None,  # the default notify path
            app_private_key_string=app_private_key_string,
            alipay_public_key_string=alipay_public_key_string,
            # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
            sign_type="RSA2",  # RSA or RSA2
            debug=True  # False by default
        )
        # 调用支付接口
        # 电脑网站支付，需要跳转到https://openapi.alipaydev.com/gateway.do? + order_string
        total_pay = order.total_price + order.transit_price  # Decimal
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order_id,  # 订单id
            total_amount=str(total_pay),  # 支付总金额
            subject='天天生鲜%s' % order_id,
            return_url=None,
            notify_url=None  # 可选, 不填则使用默认notify url
        )
        print("order_id",order_id)
        # 返回应答
        pay_url = 'https://openapi.alipaydev.com/gateway.do?' + order_string
        return JsonResponse({'res': 3, 'pay_url': pay_url})


# /order/check
class OrderCheckPayView(View):
    """ 订单支付状态查询"""

    def post(self, request):
        # 用户登录
        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': "用户未登录"})
        # 接受参数
        order_id = request.POST.get('order_id')

        # 校验参数
        if not order_id:
            return JsonResponse({'res': 1, 'errmsg': "无效的订单编号"})
        try:
            order = OrderInfo.objects.get(order_id=order_id,
                                          user=user,
                                          pay_method=3,
                                          order_status=1)
        except OrderInfo.DoesNotExist:
            return JsonResponse({'res': 2, 'errmsg': "订单错误"})

        # 业务处理 使用python sdk调用阿里支付接口
        app_private_key_string = open(os.path.join(settings.BASE_DIR, 'apps/order/app_private_key.pem')).read()
        alipay_public_key_string = open(os.path.join(settings.BASE_DIR, 'apps/order/alipay_public_key.pem')).read()
        alipay = AliPay(
            appid="2016102300747753",
            app_notify_url=None,  # the default notify path
            app_private_key_string=app_private_key_string,
            alipay_public_key_string=alipay_public_key_string,
            # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
            sign_type="RSA2",  # RSA or RSA2
            debug=True  # False by default
        )
        # 调用支付宝查询接口
        while True:
            response = alipay.api_alipay_trade_query(order_id)
            """
                    response = {
                      "alipay_trade_query_response": {
                        "trade_no": "2017032121001004070200176844", # 支付宝交易号
                        "code": "10000",# 返回接口调用状态码
                        "invoice_amount": "20.00",
                        "open_id": "20880072506750308812798160715407",
                        "fund_bill_list": [
                          {
                            "amount": "20.00",
                            "fund_channel": "ALIPAYACCOUNT"
                          }
                        ],
                        "buyer_logon_id": "csq***@sandbox.com",
                        "send_pay_date": "2017-03-21 13:29:17",
                        "receipt_amount": "20.00",
                        "out_trade_no": "out_trade_no15",
                        "buyer_pay_amount": "20.00",
                        "buyer_user_id": "2088102169481075",
                        "msg": "Success",
                        "point_amount": "0.00",
                        "trade_status": "TRADE_SUCCESS", # 支付结果
                        "total_amount": "20.00"
                      },
                      "sign": ""
                    }
                    """
            code = response.get('code')
            if code == '10000' and response.get('trade_status') == 'TRADE_SUCCESS':
                # 支付成功
                # 获取到支付交易号
                trade_no = response.get("trade_no")

                # 更新订单状态
                order.trade_no = trade_no
                order.order_status = 4  # 待评价
                order.save()

                # 返回结果
                return JsonResponse({'res': 3, 'errmsg': "支付成功"})
            elif code == '40004' or (code == '10000' and response.get('trade_status') == 'WAIT_BUYER_PAY'):
                # 交易创建，等待买家付款
                import time
                time.sleep(10)
                continue
            else:
                # 交易出错
                print("code:", code)
                return JsonResponse({'res': 4, 'errmsg': "支付失败"})


# /order/comment/order_id
class OrderCommentView(View):
    """订单评论"""

    def get(self, request, order_id):
        """提供评论页面"""
        user = request.user

        # 校验数据
        if not order_id:
            return redirect(reverse('user:order'))

        try:
            order = OrderInfo.objects.get(order_id=order_id, user=user)
        except OrderInfo.DoesNotExist:
            return redirect(reverse("user:order"))
        # 根据订单的状态获取订单的状态标题
        order.status_name = OrderInfo.ORDER_STATUS[order.order_status]

        # 获取订单商品信息
        order_skus = OrderGoods.objects.filter(order_id=order_id)
        for order_sku in order_skus:
            # 计算商品的小计
            amount = order_sku.count * order_sku.price
            # 动态给order_sku增加属性amount,保存商品小计
            order_sku.amount = amount
        # 动态给order增加属性order_skus, 保存订单商品信息
        order.order_skus = order_skus

        # 使用模板
        return render(request, "order_comment.html", {"order": order})

    def post(self, request, order_id):
        """处理评论内容"""
        user = request.user
        # 校验数据
        if not order_id:
            return redirect(reverse('user:order'))

        try:
            order = OrderInfo.objects.get(order_id=order_id, user=user)
        except OrderInfo.DoesNotExist:
            return redirect(reverse("user:order"))

        # 获取评论条数
        total_count = request.POST.get("total_count")
        total_count = int(total_count)

        # 循环获取订单中商品的评论内容
        for i in range(1, total_count + 1):
            # 获取评论的商品的id
            sku_id = request.POST.get("sku_%d" % i)  # sku_1 sku_2
            # 获取评论的商品的内容
            content = request.POST.get('content_%d' % i, '')  # cotent_1 content_2 content_3
            try:
                order_goods = OrderGoods.objects.get(order=order, sku_id=sku_id)
            except OrderGoods.DoesNotExist:
                continue

            order_goods.comment = content
            order_goods.save()

        order.order_status = 5  # 已完成
        order.save()

        return redirect(reverse("user:order", kwargs={"page": 1}))